package com.ir;

import java.util.ArrayList;
import java.util.List;

import com.asm.DirectMemoryReference;
import com.asm.IndirectMemoryReference;
import com.asm.MemoryReference;
import com.asm.Register;
import com.asm.Symbol;
import com.sysdep.CodeGenerator;

public class Var extends Expr {
    String type;
    String name;
    Expr expr;
    List<Expr> shape;
    List<Expr> value_list;
    boolean isConst = false;
    boolean isArray = false;
    boolean isGloabl;
    boolean isInited = false;
    List<List<Expr>>index;    //获取元素时的下标
    MemoryReference reference;
    int arraySize=0; //数组元素个数
    int addNum=0; //中间语言
    public int armNum=0; //arm汇编
    public boolean isParam=false;

    public Var(String type, String name, Expr expr,
            boolean isConst, boolean isArray, boolean isGloabl) {
        this.type = type;
        this.name = name;
        this.expr = expr;
        this.isConst = isConst;
        this.isArray = isArray;
        this.isGloabl = isGloabl;
        this.index=new ArrayList<>();
        addNum=0;
        armNum=0;
    }

    public void setIndex(List<Expr>index){
        // int x=0;
        // if(index.size()==0)
        //     x=-1;
        // for(int i=0;i<index.size();i++){
        //     int t=1;
        //     for(int j=i+1;j<index.size();j++){
        //         t=t*shape.get(j).getIntValue();
        //     }
        //         x=x+index.get(i).getIntValue()*t;
        // }

        addNum++;
        //System.out.println(x);
        this.index.add(index);
    }

    public List<Expr> getIndex(){
        //System.out.println(armNum);
        List<Expr> x=index.get(armNum);
        armNum++;
        return x;
    }

    public void setArray(boolean array) {
        isArray = array;
    }

    public void setExpr(Expr expr) {
        this.expr = expr;
    }

    public void setValue_list(List<Expr> value_list) {
        if(value_list==null){
            this.value_list=new ArrayList<>();
            for(int i=0;i<arraySize;i++)
                if(type.equals("int"))
                    this.value_list.add(new Int("name",0));
                else
                    this.value_list.add(new FloatIR("name",0));
        }   
        else
            this.value_list = value_list;
    }

    public void setShape(List<Expr> shape){
        this.shape=shape;
        arraySize=1;
        for(Expr expr:shape){
            arraySize*=expr.getIntValue();
        }
    }

    public String getType() {
        return type;
    }

    public String getName() {
        return name;
    }

    public Expr getExpr() {
        return expr;
    }

    public List<Expr> getValue_list() {
        return value_list;
    }

    public List<Expr> getShape() {
        
        return shape;
    }

    public boolean isArray() {
        return isArray;
    }

    public boolean isConst() {
        return isConst;
    }

    public void setGlobal(boolean global) {
        isGloabl = global;
    }

    public boolean isGloabl() {
        return isGloabl;
    }

    public boolean isInited() {
        return isInited;
    }

    public void Init() {
        isInited = true;
    }

    public void setMemoryReference(Register reg, long offset) {
        reference = new IndirectMemoryReference(offset, reg);
    }

    public void setMemoryReference(Symbol sym) {
        reference = new DirectMemoryReference(sym);
    }

    public void setMemoryReference(Symbol sym, long offset, boolean isGlobal) {
        reference = new DirectMemoryReference(sym, offset, isGlobal);
    }

    public int getArraySize() {
        return arraySize;
    }

    public MemoryReference getMemRef() {
        if (reference == null) {
            //System.out.println("mem is null");
            return null;// error
        }
        //System.out.println("mem is not null");
        return reference;
    }

    public String toString() {
        if(isArray)
        {
            String s=name;
            for(Expr expr:shape)
                s=s+"["+expr+"]";
            s=s+"={";
            if(value_list!=null)
            for(Expr expr:value_list)
                s=s+expr+",";
            s=s+"}";
            return s;
        }
        else if(expr == null){
            return name;
        }
        else
            return name+" = "+expr.toString();
    }

    @Override
    public boolean accept(CodeGenerator cg) {
        return cg.visit(this);
    }
    @Override
    public int getIntValue() {
        if(expr == null)
            return 0;
            //throw new Error("getIntValue() not supported in Var");
        else
            return expr.getIntValue();
    }
}
